EC2 인스턴스에 MySQL을 설치하여 MySQL로 리전 간 데이터 복제를 실시해 봤습니다.
안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 EC2 인스턴스에 MySQL을 설치하여 MySQL로 리전 간 데이터 복제를 실시해 봤습니다.
하고싶은 것
이번 블로그에서 다루고자 하는 것은 리전 간 MySQL 데이터 복제입니다.
A리전과 B리전의 프라이빗 서브넷에 EC2 인스턴스를 생성하고 해당 EC2 인스턴스에는 MySQL을 설치합니다. 그리고 A리전이 Master, B리전이 Slave로 Master의 데이터를 Slave로 복제하여 DR 환경을 구성합니다. Amazon RDS 혹은 AWS Backup이 아닌 MySQL의 기능을 사용하여 DR 환경을 구성할 계획입니다.
사전 준비
데이터를 복제하기에 앞서 몇 가지 사전 준비가 필요합니다.
먼저 보안 그룹의 경우 A리전의 EC2 인스턴스에는 B 리전의 인스턴스 IP를 3306 포트로 접속할 수 있도록 허용하고, 반대로 B 리전의 인스턴스에는 A 리전의 인스턴스 IP를 3306 포트로 접속할 수 있도록 허용합니다.
※ ICMP는 서로 제대로 통신이 되어있는지 핑을 날려보기 위해 추가한 것입니다.
같은 리전내 인스턴스 간 통신이었다면 보안 그룹으로 충분하지만, 리전 간 통신이기 때문에 보안 그룹을 설정할 수 없으므로 IP 주소를 직접 설정합니다.
이어서 VPC간 통신을 위해 VPC 피어링을 설정합니다.
VPC 피어링 설정에 대해서는 아래 블로그를 참고해 주세요.
EC2 인스턴스가 배치되어 있는 프라이빗 서브넷의 라우팅 테이블에 VPC 피어링을 추가합니다.
MySQL 복제 설정
이제 사전 준비가 끝났으면 복제 설정을 진행해 보도록 하겠습니다.
※ MySQL 설치에 관한 부분은 생략합니다.
mysql> CREATE USER 'replica_user'@'%' IDENTIFIED BY 'your_password';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replica_user'@'%';
mysql> FLUSH PRIVILEGES;
먼저 복제에 사용할 사용자를 생성합니다. 해당 사용자는 A 리전의 EC2 인스턴스의 MySQL입니다.
※ 모든 권한을 가진 루트로 무언가를 수행하는 건 되도록 피하는 편이 좋습니다.
sudo vi /etc/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=1
sudo systemctl restart mysqld
이어서 my.conf에서 MySQL의 설정을 변경하고 재시작합니다.
server-id는 각 MySQL의 고유한 ID이며, Master는 1로 설정합니다.
log_bin는 바이너리 로그 파일 경로를 의미하며 이 파일은 Slave에 복제할 데이터를 저장합니다.
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 157 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
마지막으로 MySQL로 접속한 다음, Master의 정보를 확인합니다.
File은 로그 파일의 이름을 의미하며, Position은 로그 파일의 위치를 의미합니다. Slave 설정에 필요하므로 메모합니다.
sudo vi /etc/my.cnf
[mysqld]
server-id=2
relay_log=/var/log/mysql/mysql-relay-bin.log
sudo systemctl restart mysqld
이제 리전 B로 넘어와서 MySQL 설정을 수정합니다.
relay_log는 리전 A에서 받아온 데이터를 보존할 로그 경로입니다.
sudo mkdir -p /var/log/mysql
sudo chown mysql:mysql /var/log/mysql
앞서 설정한 relay_log 경로가 없다면 디렉토리를 생성하고 권한을 할당합니다.
mysql> CHANGE MASTER TO
MASTER_HOST='master_ec2_ip',
MASTER_USER='replica_user',
MASTER_PASSWORD='your_password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=12345;
이제 MySQL로 접속하여 Master 정보를 설정합니다.
※ 리전 B의 MySQL입니다.
- MASTER_HOST : 리전 A의 EC2 인스턴스 IP 주소
- MASTER_USER : 복제를 위해 생성한 사용자 이름
- MASTER_PASSWORD : 복제를 위해 생성한 사용자 비밀번호
- MASTER_LOG_FILE : SHOW MASTER STATUS로 확인한 로그 파일 이름
- MASTER_LOG_POS : MASTER_LOG_POS로 확인한 로그 파일 위치
복제 시작
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
START SLAVE 명령어로 Slave를 시작합니다. 이어서 SHOW SLAVE STATUS\G; 명령어를 통해 Slave 상황을 확인할 수 있습니다. 여기서 중요한 건 Slave_IO_Running: Yes, Slave_SQL_Running: Yes 이 두 항목이 Yes로 나와있어야 정상 통신을 하고 있는 것이므로 No라고 표시된다면 보안 그룹과 같은 네트워크 설정을 다시 한 번 확인 하도록 합니다.
※ Slave_IO_Running의 경우 Yes로 변하기까지 몇 분 정도의 시간이 소요됩니다.
mysql> STOP SLAVE;
mysql> RESET SLAVE ALL;
혹은 리전 B에서 입력했던 Master 정보가 틀렸다면 Slave_IO_Running이 No로 표시될 수 있기 떄문에 이런 경우 Slave를 멈춘 다음 초기화 하고 다시 설정하도록 합니다.
mysql> CREATE DATABASE testdb;
mysql> USE testdb;
mysql> CREATE TABLE test_table (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
mysql> INSERT INTO test_table (name) VALUES ('Alice'), ('Bob'), ('Charlie');
테스트를 위해 리전 A에서 데이터베이스를 생성하고 테이블 생성후 데이터를 삽입합니다.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
+--------------------+
5 rows in set (0.01 sec)
리전 B로 넘어와서 확인해 보면 testdb가 생성되어 있습니다.
mysql> select * from test_table;
+----+---------+
| id | name |
+----+---------+
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
+----+---------+
3 rows in set (0.00 sec)
테이블도 확인해 보면 문제 없이 데이터가 출력되는 것을 확인할 수 있습니다.
이렇게 복제된 데이터는 Read/Write로 사용할 수 있으며, Slave에서 Master로 승격하고자 하는 경우 RESET SLAVE ALL;을 통해 완전히 초기화 시켜버리면 Master로 사용할 수 있습니다.
본 블로그 게시글을 읽고 궁금한 사항이 있으신 분들은 [email protected]로 보내주시면 감사하겠습니다.